/*Slide 41 in  Introduction to Parallel I/O
 * Best practices slides 50-52
 *
 * Jumpshot and MPE tools
 * http://www.mcs.anl.gov/perfvis
 TAU
 * http://www.cs.uoregon.edu/research/tau/home.php
 Intel Trace Analyzer and Collector (formerly Pallas Vampir)
 * http://www.intel.com/cd/software/products/asmo-na/eng/cluster/tanalyzer/index.htm
 Paradyn
 * http://www.cs.wisc.edu/~paradyn
 Pablo
 * http://www.renci.org/software/
 Many other vendor tools exist
 * e.g., xmpi (SGI and HP)
 *
 * Reads matrix in DCSC format
 * IR and NUM are layout out in contigously
 *
 * */
#include <stdlib.h>
#include <stdio.h>
#include "mpi.h"

int main(int argc, char* argv[]) {
	int np, myid;
	int JC_count, CP_count, IR_count, NUM_count;
	MPI_Offset offset;
	MPI_File myfile; /* Shared file */
	MPI_Status status; /* Status returned from read */

	/* Initialize MPI */
	MPI_Init(&argc, &argv);
	MPI_Comm_rank(MPI_COMM_WORLD, &myid);
	MPI_Comm_size(MPI_COMM_WORLD, &np);

	/* Open the file */
	MPI_File_open(MPI_COMM_WORLD, "dcsc_mat.bin", MPI_MODE_RDONLY,
			MPI_INFO_NULL, &myfile);
	int * header = (int*) malloc(4 * sizeof(int));
	MPI_File_read(myfile, header, 4, MPI_INT, &status);
	// Set sizes of arrays
	JC_count = header[0];
	CP_count = header[1];
	IR_count = header[2];
	NUM_count = header[3];


	// Read arrays JC and CP
	int JC_CP[JC_count + CP_count];
	MPI_File_read(myfile, &JC_CP, JC_count + CP_count, MPI_INT, &status);
	MPI_File_get_position(myfile, &offset);
	int jc_idx = (int) (JC_count / np) * myid;
	printf("read aux arrays. JC=%d, CP=%d, IR=%d, NUM=%d, jc_idx=%d\n", JC_count, CP_count,IR_count,NUM_count, jc_idx);
	int *IR;
	float * NUM;
	while (JC_CP[jc_idx] != -1) {
		int ir_start = JC_CP[JC_count + jc_idx];
		int ir_end = JC_CP[JC_count + jc_idx + 1];
		int buflen = ir_end - ir_start;
		MPI_Alloc_mem(sizeof(int) * buflen, MPI_INFO_NULL, &IR);
		MPI_Alloc_mem(sizeof(float) * buflen, MPI_INFO_NULL, &NUM);
		MPI_File_read_at(myfile, offset + (ir_start * sizeof(int)), IR, buflen,MPI_INT, &status);
		MPI_File_read_at(myfile, offset + ((ir_start + IR_count) * sizeof(float)), NUM, buflen, MPI_FLOAT,
				&status);

		JC_CP[jc_idx]= -1;
		jc_idx = (jc_idx+1) % JC_count;
/*
		printf("jc_idx=%d", jc_idx);
		for (int i = 0; i < buflen; i++) {
			printf("(%d, %.2f)", IR[i], NUM[i]);
		}
		printf("\n", "");*/

		MPI_Free_mem(IR);
		MPI_Free_mem(NUM);
	}
/*
	int j;
	// read column index at position "jc_idx"
	MPI_File_read_at(myfile, offset + jc_idx * sizeof(int), &j, 1, MPI_INT,
			&status);

	printf("J : %d\n", j);
	int * nzc = (int*) malloc(2 * sizeof(int));
	// Read the bounds of indices for IR
	MPI_File_read_at(myfile, offset + ((jc_idx + JC_count) * sizeof(int)), nzc,
			2, MPI_INT, &status);
	printf("NZC %d\n", nzc[1] - nzc[0]);
	int * IR = (int*) malloc(nzc[1] - nzc[0] * sizeof(int));
	// Read the row indices for column
	MPI_File_read_at(myfile,
			offset + ((jc_idx + JC_count + CP_count) * sizeof(int)), IR,
			nzc[1] - nzc[0], MPI_INT, &status);

	for (int i = 0; i < nzc[1] - nzc[0]; i++) {
		printf("IR at %d: %d\n", i, IR[i]);
	}
	// Read the values for elements
	float * NUM = (float*) malloc((nzc[1] - nzc[0]) * sizeof(float));
	MPI_File_read_at(myfile,
			offset + ((jc_idx + JC_count + CP_count + IR_count) * sizeof(int)),
			NUM, nzc[1] - nzc[0], MPI_FLOAT, &status);
	for (int i = 0; i < (nzc[1] - nzc[0]); i++) {
		printf("NUM at %d: %.4f\n", i, NUM[i]);
	}*/

	/* Close the file */
	MPI_File_close(&myfile);

	MPI_Finalize();
	exit(0);
}

/*
 Get the size of the file
 MPI_File_get_size(myfile, &filesize);
 Calculate how many elements that is
 filesize = filesize / sizeof(char);
 Calculate how many elements each processor gets
 //bufsize = filesize/np;
 bufsize = filesize;
 Allocate the buffer to read to, one extra for terminating null char
 buf = (char *) malloc((bufsize + 1) * sizeof(char));
 Set the file view
 MPI_File_set_view(myfile, 0 * bufsize * sizeof(char), MPI_CHAR, MPI_BYTE,
 "native", MPI_INFO_NULL);
 Read from the file
 MPI_File_read(myfile, buf, bufsize, MPI_CHAR, &status);
 Find out how many elemyidnts were read

 MPI_Get_count(&status, MPI_BYTE, &nrchar);
 Set terminating null char in the string
 buf[nrchar] = (char) 0;
 printf("Process %2d read %d characters: ", myid, nrchar);
 printf("  %s\n", buf);
 */
